﻿using Subfaculty.Controllers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting.Web;
using RepositoriesInterfaces;
using System.Web.Mvc;
using Moq;
using Entities;
using System.Collections.Generic;
using Subfaculty.ViewModels;

namespace TestsSubfaculty
{
    [TestClass()]
    public class LoadDistributionControllerTest
    {
        private readonly Mock<ILoadAtomRepository> LoadAtomRep;
        private readonly Mock<IDepartmentRepository> DepartmentRep;
        private readonly Mock<ITeacherRepository> TeacherRep;

        private IList<LoadAtom> LoadAtomList;
        private IList<Department> DepartmentList;
        private IList<Teacher> TeacherList;


        public LoadDistributionControllerTest()
        {
            LoadAtomRep = new Mock<ILoadAtomRepository>();
            TeacherRep = new Mock<ITeacherRepository>();
            DepartmentRep = new Mock<IDepartmentRepository>();
            LoadAtomList = new List<LoadAtom>();            
            DepartmentList = new List<Department>();
            TeacherList = new List<Teacher>();
        }

        [TestMethod]
        public void GetLoadsLists_LoadDistribController() // получить спиcки распределенной и нераспределенной нагрузки
        {
            // 1. Инициализация
            DepartmentRep.Setup(x => x.GetAll()).Returns(DepartmentList);
            TeacherRep.Setup(x => x.GetByID(0)).Returns(new Teacher(){ Id = 0 });
            TeacherRep.Setup(x => x.GetByDepartmentId(0)).Returns(TeacherList);
            LoadAtomRep.Setup(x => x.GetDistributionLoad(0, 0)).Returns(LoadAtomList);
            LoadAtomRep.Setup(x => x.GetNotDistributionLoad(0)).Returns(LoadAtomList);
            
            // 2. Вызов метода
            var LoadDistribController = new LoadDistributionController(DepartmentRep.Object, LoadAtomRep.Object, TeacherRep.Object);
            var result = LoadDistribController.Index(0) as ViewResult;

            // 3. Проверка результата
            var returnedModel = (LoadDistributionViewModel)result.Model;
            Assert.AreEqual(LoadAtomList, returnedModel.distributionLoad);
            Assert.AreEqual(LoadAtomList, returnedModel.notDistributionLoad);
            Assert.AreEqual(TeacherList, returnedModel.teachersList);
        }

        [TestMethod]
        public void GetDistributedLoadsList_LoadDistribController() 
        {
            // 1. Инициализация
            Teacher teacher = new Teacher();
            TeacherRep.Setup(x => x.GetByID(0)).Returns(teacher);            
            LoadAtomRep.Setup(x => x.GetDistributionLoad(It.IsAny<int>(), 0)).Returns(LoadAtomList);
            
            // 2. Вызов метода
            var LoadDistribController = new LoadDistributionController(DepartmentRep.Object, LoadAtomRep.Object, TeacherRep.Object);
            var result = LoadDistribController.ajaxUpdateDistrTree(0) as PartialViewResult;

            // 3. Проверка результата
            var returnedModel = (AjaxUpdateDistrTreeViewModel)result.Model;
            Assert.AreEqual(LoadAtomList, returnedModel.distributionLoad);
            Assert.AreEqual(teacher, returnedModel.teacher);
        }

        [TestMethod]
        public void GetNotDistributedLoadsList_LoadDistribController()
        {
            // 1. Инициализация
            LoadAtomRep.Setup(x => x.GetNotDistributionLoad(0)).Returns(LoadAtomList);

            // 2. Вызов метода
            var LoadDistribController = new LoadDistributionController(DepartmentRep.Object, LoadAtomRep.Object, TeacherRep.Object);
            var result = LoadDistribController.ajaxUpdateNotDistrTree(0) as PartialViewResult;

            // 3. Проверка результата
            var returnedModel = (AjaxUpdateNotDistrTreeViewModel)result.Model;
            Assert.AreEqual(LoadAtomList, returnedModel.NotDistributionLoad);
        }

        [TestMethod]
        public void DistributeAtomToTeacher_LoadDistribController() // Назначить один атом преподавателю
        {
            // 1. Инициализация
            Teacher teacher = new Teacher();
            LoadAtom distributedAtom = new LoadAtom();
            TeacherRep.Setup(x => x.GetByID(0)).Returns(teacher);
            LoadAtomRep.Setup(x => x.GetByID(0)).Returns(distributedAtom);
            TeacherRep.Setup(x => x.SaveOrUpdate(teacher));

            // 2. Вызов метода
            var LoadDistribController = new LoadDistributionController(DepartmentRep.Object, LoadAtomRep.Object, TeacherRep.Object);
            String result = LoadDistribController.ajaxDistributeAtom(0, 0);

            // 3. Проверка результата            
            Assert.AreEqual(result, "ok");
            Assert.AreEqual(distributedAtom.Teacher, teacher);
            Assert.AreEqual(teacher.LoadAtoms.Contains(distributedAtom), true);
        }

        [TestMethod]
        public void DistributeGroupAtomByTypeToTeacher_LoadDistribController() // Назначить группу атомов одного типа нагрузки преподавателю
        {
            // 1. Инициализация
            Teacher teacher = new Teacher();
            LoadAtomList.Add(new LoadAtom()); LoadAtomList.Add(new LoadAtom()); LoadAtomList.Add(new LoadAtom());
            TeacherRep.Setup(x => x.GetByID(It.IsAny<int>())).Returns(teacher);
            LoadAtomRep.Setup(x => x.GetByDisciplineAndType(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<String>(), It.IsAny<Teacher>())).Returns(LoadAtomList);
            TeacherRep.Setup(x => x.SaveOrUpdate(teacher));

            // 2. Вызов метода
            var LoadDistribController = new LoadDistributionController(DepartmentRep.Object, LoadAtomRep.Object, TeacherRep.Object);
            String result = LoadDistribController.ajaxDistributeLoadType(0, 0, "Lectures");

            // 3. Проверка результата            
            Assert.AreEqual(result, "ok");
            foreach (LoadAtom atom in LoadAtomList)
            {
                Assert.AreEqual(teacher.LoadAtoms.Contains(atom), true);
                Assert.AreEqual(atom.Teacher, teacher);
            }
        }

        [TestMethod]
        public void DistributeGroupAtomByDisciplineToTeacher_LoadDistribController() // Назначить все атомы конкретной дисциплины преподавателю
        {
            // 1. Инициализация
            Teacher teacher = new Teacher();
            LoadAtomList.Add(new LoadAtom()); LoadAtomList.Add(new LoadAtom()); LoadAtomList.Add(new LoadAtom());
            TeacherRep.Setup(x => x.GetByID(It.IsAny<int>())).Returns(teacher);
            LoadAtomRep.Setup(x => x.GetByDiscipline(It.IsAny<int>(), It.IsAny<int>(), null)).Returns(LoadAtomList);
            TeacherRep.Setup(x => x.SaveOrUpdate(teacher));

            // 2. Вызов метода
            var LoadDistribController = new LoadDistributionController(DepartmentRep.Object, LoadAtomRep.Object, TeacherRep.Object);
            String result = LoadDistribController.ajaxDistributeLoadDiscipline(0, 0);

            // 3. Проверка результата            
            Assert.AreEqual(result, "ok");
            foreach (LoadAtom atom in LoadAtomList)
            {
                Assert.AreEqual(teacher.LoadAtoms.Contains(atom), true);
                Assert.AreEqual(atom.Teacher, teacher);
            }
        }
    }
}

